package com.dragon.mmochat.service;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.dragon.mmochat.MmochatConstant;
import com.dragon.mmochat.MmochatMain;
import com.dragon.mmochat.message.Mmochat_1_11C;
import com.dragon.mmochat.message.Mmochat_1_11S;
import com.dragon.mmochat.message.Mmochat_EnterOtherServerMap;
import com.dragon.mmochat.message.Mmochat_ServerInfoMessage;
import com.dragon.mmochat.message.Mmochat_ServerListInfoMessage;
import com.dragon.mmochat.message.Mmochat_ServerStateMessage;
import com.dragon.mmochat.model.MmochatAnnouncement;
import com.dragon.mmochat.model.MmochatServerInfo;
import com.dragon.mmochat.model.MmochatWuDaoWinWords;
import com.dragon.mmochat.model.enumType.MmochatAnnouncementFilter;
import com.dragon.mmochat.model.enumType.MmochatServerStateType;
import com.dragon.mmochat.model.enumType.MmochatServerType;
import com.dragon.mmochat.model.role.MmochatPlayer;
import com.dragon.mmochat.util.MmochatUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.skymobi.handler.SkymobiHandler;
import com.skymobi.message.SkymobiProtocolMessage;
import com.skymobi.service.SkymobiService;

//服务器列表
public class MmochatServerListService {
	private static Logger log = LoggerFactory
			.getLogger(MmochatServerListService.class);

	public static ScheduledExecutorService serverListThread = Executors
			.newScheduledThreadPool(1);

	public static ScheduledExecutorService clientVersionThread = Executors
			.newScheduledThreadPool(1);

	// 服务器列表:实例号-->MmochatServerInfo
	public static Map<Integer, MmochatServerInfo> serverInstanceMap = new ConcurrentHashMap<Integer, MmochatServerInfo>();

	// 服务器列表
	public static List<MmochatServerInfo> serverList = new ArrayList<MmochatServerInfo>();

	// Gson:服务器ID-->实例号
	public static String gson_serverMap = null;

	// 上一次配置文件修改时间
	private static long lastModifyTimeOfServerListFile = 0;

	// 上一次公告文件修改时间
	private static long lastModifyTimeOfBBSFile = 0;

	private static long lastModifyTimeOfClientVersionFile = 0;

	// 公告信息列表
	public static List<MmochatAnnouncement> announcements = new ArrayList<MmochatAnnouncement>();

	public void init() {
		if (!MmochatMain.openMergeServer) {
			if (MmochatMain.getModuleInstID() == MmochatConstant.serverListModuleId) {
				// serverList服务器,每5分钟判断一次是否需要从配置文件重新读取服务器列表
				log.debug("this is listServer!");
				MmochatMain.setServerName("服务器列表");
				serverListThread.scheduleWithFixedDelay(new loadServerList(),
						0, 5, TimeUnit.MINUTES);
			} else {
				// 游戏服务器,每5分钟向serverList汇报一次当前服的信息
				log.debug("this is gameServer!");
				serverListThread.scheduleWithFixedDelay(new sendServerInfo(),
						30, 5 * MmochatConstant.SECOND_PER_MIN,
						TimeUnit.SECONDS);
			}

			// 每5分钟判断一次是否需要从配置文件重新读取clientVersion
			clientVersionThread.scheduleWithFixedDelay(new loadClientVersion(),
					0, 5, TimeUnit.MINUTES);
		}
	}

	// 获取有效公告列表
	@SuppressWarnings("deprecation")
	public static List<MmochatAnnouncement> getValidAnnouncement(
			MmochatPlayer me) {
		List<MmochatAnnouncement> list = new ArrayList<MmochatAnnouncement>();

		Date now = new Date();

		// 跨服王者宣言
		try {
			if (now.getDay() == 4 || now.getDay() == 5) {
				int myRange = me.getLevel() / 10 * 10;
				List<MmochatWuDaoWinWords> words = new ArrayList<MmochatWuDaoWinWords>();
				for (MmochatWuDaoWinWords word : MmochatNpcService.mixWuDaoWinWords
						.values()) {
					try {
						if (!word.isValid()) {
							MmochatNpcService.mixWuDaoWinWords.remove(word
									.getRoleId());
						}
					} catch (Exception e) {
						e.printStackTrace();
					}

					if (word.getLevelRange() == myRange) {
						words.add(word);
					}
				}
				if (words.size() > 0) {
					MmochatAnnouncement info = new MmochatAnnouncement();
					info.setId(-1000 - 1 * myRange);
					info.setTitle("跨服王者胜利宣言");
					info.setTitleColor(Color.magenta);
					info.setTimeInfo(myRange + "级跨服王者");
					String detail = "";
					for (MmochatWuDaoWinWords word : words) {
						detail += MmochatUtil.wrapColor("["
								+ word.getServerName() + "]\n", Color.red);
						break;
					}
					for (MmochatWuDaoWinWords word : words) {
						detail += MmochatUtil.wrapColor(word.getName() + "\n",
								Color.magenta);
						detail += word.getWords() + "\n\n";
					}
					info.setDetail(detail);
					list.add(info);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 试道王者宣言
		try {
			if (now.getDay() == 1 || now.getDay() == 2) {
				int myRange = me.getLevel() / 10 * 10;
				List<MmochatWuDaoWinWords> words = new ArrayList<MmochatWuDaoWinWords>();
				for (MmochatWuDaoWinWords word : MmochatNpcService.wuDaoWinWords
						.values()) {
					try {
						if (!word.isValid()) {
							MmochatNpcService.wuDaoWinWords.remove(word
									.getRoleId());
						}
					} catch (Exception e) {
						e.printStackTrace();
					}

					if (word.getLevelRange() == myRange) {
						words.add(word);
					}
				}
				if (words.size() > 0) {
					MmochatAnnouncement info = new MmochatAnnouncement();
					info.setId(-1 * myRange);
					info.setTitle("试道王者胜利宣言");
					info.setTitleColor(Color.green);
					info.setTimeInfo(myRange + "级试道王者");
					String detail = "";
					for (MmochatWuDaoWinWords word : words) {
						detail += MmochatUtil.wrapColor(word.getName() + "\n",
								Color.magenta);
						detail += word.getWords() + "\n\n";
					}
					info.setDetail(detail);
					list.add(info);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 如果有预充值活动，则自动增加此公告
		if (MmochatGmService.isTodayDelayPayOpen()) {
			if (me.getLatest_pay_time() > 0 && me.getLevel() >= 30) {
				MmochatAnnouncement info = new MmochatAnnouncement();
				info.setId(-1);
				info.setTitle("预充值活动开启");
				info.setTitleColor(Color.red);
				info.setTimeInfo("今日0:00-23:59");
				info.setDetail("详见9键商城里充值元宝中的充值卡预充值活动。"
						+ "预充值后，元宝不是马上到账，一般在1至12小时内到账，兑换比例有一定优惠。"
						+ "此活动为临时活动，只有在活动期间，在充值页面才能看到此活动项。");
				list.add(info);
			}
		}

		for (MmochatAnnouncement info : announcements) {
			if (System.currentTimeMillis() >= info.getStartTick()
					&& System.currentTimeMillis() < info.getEndTick()) {
				if (info.getFilter() == MmochatAnnouncementFilter.所有人查看) {
					list.add(info);
				} else if (info.getFilter() == MmochatAnnouncementFilter.充值用户查看) {
					if (me.getLatest_pay_time() > 0 && me.getLevel() >= 30) {
						list.add(info);
					}
				}
			}
		}
		return list;
	}

	// 读取版本号
	class loadClientVersion implements Runnable {
		public void run() {
			try {
				File file = new File("config/clientVersion.xml");
				if (file.isFile()) {
					if (lastModifyTimeOfClientVersionFile == file
							.lastModified()) {
						// 未修改
					} else {
						log.debug("start loading clientVersion...");

						lastModifyTimeOfClientVersionFile = file.lastModified();

						DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
								.newInstance();
						DocumentBuilder docBuilder;
						docBuilder = docBuilderFactory.newDocumentBuilder();
						Document doc = docBuilder.parse(file);
						doc.getDocumentElement().normalize();

						// 读取终端ID
						NodeList listOfClientVersion = doc
								.getElementsByTagName("mmochat");
						if (listOfClientVersion.getLength() > 0) {
							Node node = listOfClientVersion.item(0);
							if (node.getNodeType() == Node.ELEMENT_NODE) {
								Element element = (Element) node;
								NodeList nodeList = element
										.getElementsByTagName("clientVersion");
								if (nodeList.getLength() > 0) {
									String str = nodeList.item(0)
											.getChildNodes().item(0)
											.getNodeValue().trim();
									try {
										int id = Integer.parseInt(str);
										MmochatMain.setClientVersion(id);
									} catch (NumberFormatException e) {
										e.printStackTrace();
										throw new RuntimeException(
												"版本号.xml中,clientVersion不是数字!");
									}
								} else {
									throw new RuntimeException(
											"版本号.xml中,clientVersion未设置!");
								}
							}
						}
						log.debug("loading clientVersion success!");
					}
				} else {
					throw new RuntimeException("config/版本号.xml不存在");
				}
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}

			if (MmochatMain.serverType == MmochatServerType.游戏服务器) {
				// 加载公告
				try {
					File file = new File("activities/bbs.xml");
					if (file != null && file.isFile()) {
						if (lastModifyTimeOfBBSFile == file.lastModified()) {
							// 未修改
						} else {
							log.debug("start loading bbs.xml...");
							lastModifyTimeOfBBSFile = file.lastModified();

							DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
									.newInstance();
							DocumentBuilder docBuilder = docBuilderFactory
									.newDocumentBuilder();
							Document doc = docBuilder.parse(file);
							doc.getDocumentElement().normalize();
							NodeList listOfBBS = doc
									.getElementsByTagName("活动公告");
							log.debug("活动公告 num = " + listOfBBS.getLength());

							List<MmochatAnnouncement> tmp = new ArrayList<MmochatAnnouncement>();
							for (int s = 0; s < listOfBBS.getLength(); s++) {
								Node firstNpcNode = listOfBBS.item(s);
								if (firstNpcNode.getNodeType() == Node.ELEMENT_NODE) {
									MmochatAnnouncement announcement = new MmochatAnnouncement();
									Element firstNpcElement = (Element) firstNpcNode;

									// 设置ID
									announcement.setId(s);

									// 读取查看权限
									{
										NodeList node = firstNpcElement
												.getElementsByTagName("查看权限");
										if (node != null
												&& node.getLength() > 0) {
											String str = node.item(0)
													.getChildNodes().item(0)
													.getNodeValue().trim();
											if (str != null) {
												try {
													MmochatAnnouncementFilter filter = MmochatAnnouncementFilter
															.valueOf(str);
													if (filter != null) {
														announcement
																.setFilter(filter);
													}
												} catch (Exception e) {
													e.printStackTrace();
												}
											}
										}
									}

									// 读取标题
									{
										NodeList node = firstNpcElement
												.getElementsByTagName("标题");
										String str = node.item(0)
												.getChildNodes().item(0)
												.getNodeValue().trim();
										if (str != null) {
											announcement.setTitle(str);
										}
									}

									// 读取标题颜色
									{
										NodeList node = firstNpcElement
												.getElementsByTagName("标题颜色");
										String str = node.item(0)
												.getChildNodes().item(0)
												.getNodeValue().trim();
										if (str != null) {
											Color color = null;
											if (str.equals("红")) {
												color = Color.red;
											} else if (str.equals("黄")) {
												color = Color.yellow;
											} else if (str.equals("绿")) {
												color = Color.green;
											} else if (str.equals("橙")) {
												color = Color.magenta;
											}
											announcement.setTitleColor(color);
										}
									}

									// 读取活动时间描述
									{
										NodeList node = firstNpcElement
												.getElementsByTagName("活动时间描述");
										String str = node.item(0)
												.getChildNodes().item(0)
												.getNodeValue().trim();
										if (str != null) {
											announcement.setTimeInfo(str);
										}
									}

									// 读取活动详情
									{
										NodeList node = firstNpcElement
												.getElementsByTagName("活动详情");
										String str = node.item(0)
												.getChildNodes().item(0)
												.getNodeValue().trim();
										if (str != null) {
											announcement.setDetail(str);
										}
									}

									// 读取开始时间
									{
										NodeList node = firstNpcElement
												.getElementsByTagName("开始时间");
										String str = node.item(0)
												.getChildNodes().item(0)
												.getNodeValue().trim();
										if (str != null) {
											SimpleDateFormat sdf = new SimpleDateFormat(
													"yyyy-MM-dd:HH-mm-ss");
											Date start = sdf.parse(str);
											announcement.setStartTick(start
													.getTime());
										}
									}

									// 读取结束时间
									{
										NodeList node = firstNpcElement
												.getElementsByTagName("结束时间");
										String str = node.item(0)
												.getChildNodes().item(0)
												.getNodeValue().trim();
										if (str != null) {
											SimpleDateFormat sdf = new SimpleDateFormat(
													"yyyy-MM-dd:HH-mm-ss");
											Date start = sdf.parse(str);
											announcement.setEndTick(start
													.getTime());
										}
									}
									tmp.add(announcement);
								}
							}
							announcements = tmp;
						}
					}
				} catch (ParserConfigurationException e) {
					e.printStackTrace();
				} catch (SAXException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

		}

	}

	// 读取服务器列表
	class loadServerList implements Runnable {
		@Override
		public void run() {
			// 设置列表服务器在线人数
			try {
				for (MmochatServerInfo server : serverList) {
					if (server.getModuleInstID() == MmochatMain
							.getModuleInstID()) {
						server.setPlayerNum(MmochatMainService.players.size());
					}
				}
			} catch (Exception e1) {
			}

			try {
				File file = new File("config/serverList.xml");
				if (file.isFile()) {
					if (lastModifyTimeOfServerListFile == file.lastModified()) {
						// 未修改
						return;
					}
					log.debug("start loading serverList...");

					lastModifyTimeOfServerListFile = file.lastModified();
					// id->server; 用来保证id不重复
					// Map<Integer, MmochatServerInfo> newServerIdMap = new
					// ConcurrentHashMap<Integer, MmochatServerInfo>();

					List<MmochatServerInfo> serverListBak = new ArrayList<MmochatServerInfo>();

					// instanceId->server
					Map<Integer, MmochatServerInfo> newServerInstanceMap = new ConcurrentHashMap<Integer, MmochatServerInfo>();

					DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
							.newInstance();
					DocumentBuilder docBuilder;
					docBuilder = docBuilderFactory.newDocumentBuilder();
					Document doc = docBuilder.parse(file);
					doc.getDocumentElement().normalize();

					NodeList listOfServer = doc.getElementsByTagName("服务器");
					log.debug("服务器数量:" + listOfServer.getLength());

					for (int s = 0; s < listOfServer.getLength(); s++) {
						Node serverNode = listOfServer.item(s);
						if (serverNode.getNodeType() == Node.ELEMENT_NODE) {
							Element serverElement = (Element) serverNode;
							MmochatServerInfo newServer = new MmochatServerInfo();

							// 设置位置
							newServer.setIndex(s);

							// 读取名字
							{
								NodeList nodeList = serverElement
										.getElementsByTagName("名字");
								String str = nodeList.item(0).getChildNodes()
										.item(0).getNodeValue().trim();
								newServer.setName(str);
							}
							// 读取ID
							{
								NodeList nodeList = serverElement
										.getElementsByTagName("ID");
								String str = nodeList.item(0).getChildNodes()
										.item(0).getNodeValue().trim();
								try {
									int id = Integer.parseInt(str);
									newServer.setId(id);
								} catch (NumberFormatException e) {
									e.printStackTrace();
									throw new RuntimeException(
											"serverList.xml中,"
													+ newServer.getName()
													+ "服的ID不是数字!");
								}
							}
							// 读取实例号
							{
								NodeList nodeList = serverElement
										.getElementsByTagName("实例号");
								String str = nodeList.item(0).getChildNodes()
										.item(0).getNodeValue().trim();
								int instanceId;
								try {
									if (str.startsWith("0x")) {
										instanceId = Integer.parseInt(str
												.substring(2), 16);
									} else {
										instanceId = Integer.parseInt(str);
									}
								} catch (NumberFormatException e) {
									e.printStackTrace();
									throw new RuntimeException(
											"serverList.xml中,"
													+ newServer.getName()
													+ "服的实例号设置不正确!");
								}
								newServer.setModuleInstID(instanceId);
							}
							// 读取是否为新服
							{
								NodeList nodeList = serverElement
										.getElementsByTagName("新服");
								String str = nodeList.item(0).getChildNodes()
										.item(0).getNodeValue().trim();
								if (str.equals("是")) {
									newServer.setNewServer(true);
								} else {
									newServer.setNewServer(false);
								}
							}

							// 读取后台地址
							{
								NodeList nodeList = serverElement
										.getElementsByTagName("后台地址");
								String str = nodeList.item(0).getChildNodes()
										.item(0).getNodeValue().trim();
								newServer.setManageUrl(str);
							}

							// 是否为KA
							{
								NodeList nodeList = serverElement
										.getElementsByTagName("KA");
								if (nodeList != null
										&& nodeList.getLength() > 0) {
									String str = nodeList.item(0)
											.getChildNodes().item(0)
											.getNodeValue().trim();
									if (str != null && str.equals("是")) {
										newServer.setKA(true);
									}
								}
							}

							// 继承旧的内存数据
							MmochatServerInfo oldInfo = serverInstanceMap
									.get(newServer.getModuleInstID());
							if (oldInfo != null) {
								newServer.setPlayerNum(oldInfo.getPlayerNum());
								newServer.setState(oldInfo.getState());
								newServer.setStopMsg(oldInfo.getStopMsg());
							}

							serverListBak.add(newServer);
							if (newServerInstanceMap.get(newServer
									.getModuleInstID()) == null) {
								newServerInstanceMap.put(newServer
										.getModuleInstID(), newServer);
							}
						}
					}
					serverInstanceMap = newServerInstanceMap;
					serverList = serverListBak;
					Collections.sort(serverList);

					Map<Integer, Integer> serverMap = new ConcurrentHashMap<Integer, Integer>();
					for (MmochatServerInfo s : serverList) {
						serverMap.put(s.getId(), s.getModuleInstID());
					}
					MmochatMain.setServerListInfo(serverMap);
					Gson gson = new Gson();
					gson_serverMap = gson.toJson(serverMap,
							new TypeToken<Map<Integer, Integer>>() {
							}.getType());

					log.debug("loading serverList success!");
				} else {
					throw new RuntimeException("config/serverList.xml不存在");
				}
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	// 向serverList服务器发送当前本服人数信息
	class sendServerInfo implements Runnable {
		@Override
		public void run() {
			try {
				log.debug("send server info");
				Mmochat_ServerInfoMessage pack = new Mmochat_ServerInfoMessage();
				pack.setCurServerInstanceId(MmochatMain.getModuleInstID());
				pack.setCurServerPlayerNum(MmochatMainService.players.size());
				pack.setVersion(MmochatMain.getServerVersion());
				SkymobiHandler handle = MmochatMainService.getCommonHandler();
				if (handle != null) {
					handle.asyncPushSkymobiModuleMessage(pack, null);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	// 获取服务器列表
	@SkymobiService
	public SkymobiProtocolMessage handleC_1_11(SkymobiHandler handler,
			Mmochat_1_11C req) {
		// 列表服务器是不区分KA与非KA的，通过不同的终端模块号，下发KA和非KA专区
		List<MmochatServerInfo> servers = new ArrayList<MmochatServerInfo>();
		if (req.getSrcId() == MmochatConstant.ka_clientModuleId) {
			for (MmochatServerInfo ser : serverList) {
				if (ser.isKA()) {
					servers.add(ser);
				}
			}
		} else {
			for (MmochatServerInfo ser : serverList) {
				if (!ser.isKA()) {
					servers.add(ser);
				}
			}
		}
		Mmochat_1_11S pack = new Mmochat_1_11S();
		pack.setHallState(req.getHallState());
		pack.setServerList(servers);

		// 记录登陆数
		Integer loginTimes = ServerListStatistics.todayLoginSkyIdMap.get(req
				.getSkyId());
		if (loginTimes == null) {
			ServerListStatistics.todayLoginSkyIdMap.put(req.getSkyId(), 1);
		} else {
			loginTimes++;
			ServerListStatistics.todayLoginSkyIdMap.put(req.getSkyId(),
					loginTimes);
		}
		return pack;
	}

	// 获取服务器信息
	@SkymobiService
	public void handleServerInfoMessage(SkymobiHandler handler,
			Mmochat_ServerInfoMessage req) {
		int instanceId = req.getCurServerInstanceId();
		int playerNum = req.getCurServerPlayerNum();

		for (MmochatServerInfo server : serverList) {
			if (server.getModuleInstID() == instanceId) {
				server.setPlayerNum(playerNum);
				server.setState(MmochatServerStateType.运行中);
				server.setStopMsg(null);
				if ((server.getVersion() == null || (long) server.getVersion() != req
						.getVersion())
						&& gson_serverMap != null) {
					// 向目标区服发送所有区服信息:此区区名，所有区信息：ID-->实例号
					Mmochat_ServerListInfoMessage pack = new Mmochat_ServerListInfoMessage();
					pack.setDstModuleId(instanceId);
					pack.setServerName(server.getName());
					pack.setGson_serverMap(gson_serverMap);
					SkymobiHandler handle = MmochatMainService
							.getCommonHandler();
					if (handle != null) {
						handle.asyncPushSkymobiModuleMessage(pack, null);
					}

					server.setVersion(req.getVersion());
				}
				log.debug("[" + server.getName() + "]player Num="
						+ server.getPlayerNum());

			}
		}
	}

	// 获取服务器状态
	@SkymobiService
	public void handleServerStateMessage(SkymobiHandler handler,
			Mmochat_ServerStateMessage req) {
		int instanceId = req.getInstanceId();
		MmochatServerStateType state = req.getState();
		String stateMsg = req.getStateMsg();
		for (MmochatServerInfo server : serverList) {
			if (server.getModuleInstID() == instanceId) {
				server.setState(state);
				if (state == MmochatServerStateType.维护中) {
					server.setPlayerNum(0);
				}
				server.setStopMsg(stateMsg);
			}
		}
	}

	// 收到服务器列表信息
	@SkymobiService
	public void handleServerNameRetMessage(SkymobiHandler handler,
			Mmochat_ServerListInfoMessage req) {
		String serverName = req.getServerName();
		MmochatMain.setServerName(serverName);
		String str = req.getGson_serverMap();
		if (str != null) {
			Gson gson = new Gson();
			Map<Integer, Integer> serverListInfo = gson.fromJson(str,
					new TypeToken<Map<Integer, Integer>>() {
					}.getType());
			if (serverListInfo != null) {
				MmochatMain.setServerListInfo(serverListInfo);
			}
		}
	}

}
